/*
 * Copyright (c) 2012-2020
 * All Rights Reserved by Thunder Software Technology Co., Ltd and its affiliates.
 * You may not use, copy, distribute, modify, transmit in any form this file
 * except in compliance with THUNDERSOFT in writing by applicable law.
 *
 * Auther: Chi Qing  <chiqing0601@thundersoft.com>
 * Function Description: This program is used to set cpu usage.
 */

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <pthread.h>
#include <time.h>
#include <unistd.h>

typedef long long int int64;
static int g_eachTime = 1;						   //每次刷新时间, 秒
static double g_cpuInfo = 0;					   //cpu的占用率
const int NUM_CPU = sysconf(_SC_NPROCESSORS_CONF); //cpu的核数

namespace cpuLoad
{
	int64 getTickCount()
	/* 
	* name: getTickCount
	* paremets: None
	* return: int64 time
	* usage: 返回此时的时间，单位为毫秒
	*/
	{
		timespec now;
		clock_gettime(CLOCK_MONOTONIC, &now);
		int64 sec = now.tv_sec;				//s
		int64 nsec = now.tv_nsec;			//ns
		return sec * 1000 + nsec / 1000000; //ms
	}

	void *CPUCost(void *args)
	{
		cpu_set_t mask;	
		CPU_ZERO(&mask);	//清空集合
		CPU_SET((int)(long)args, &mask);	//将cpu的核加入集合
		pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask);	//设置本线程对集合内CPU的亲和性
		int busyTime = g_eachTime * 1000 * (g_cpuInfo / (double)100); //工作时间, ms
		int idleTiem = g_eachTime * 1000 - busyTime;
		int64 startTime = 0;
		while (true)
		{
			startTime = getTickCount(); //接近1 000 000 ms
			while ((getTickCount() - startTime) <= busyTime)
				;
			usleep(idleTiem * 1000); //us
		}
	}

	void pthreadOpr(int &index)
	{
		pthread_t t;
		int ret = pthread_create(&t, NULL, cpuLoad::CPUCost, (void*)(long) index);
		if (ret)
		{
			std::cout << "CpuLoad Thread create error" << std::endl;
		}
		else
		{
			std::cout << "CPU" << index << "  Cost" << std::endl;
		}
	}
} // namespace cpuLoad

int main(int argc, char **argv)
{
	std::cout << "请输入cpu占用率(单位：%): ";
	std::cin >> g_cpuInfo;
	
	std::vector<int> vcCoreNum(NUM_CPU);
	iota(vcCoreNum.begin(), vcCoreNum.end(), 0);
	for_each(vcCoreNum.begin(), vcCoreNum.end(), cpuLoad::pthreadOpr);

	pthread_exit(NULL);
	return 0;
}
